#include "cmdcard.h"
#include "commmsg.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "../card/CCardMgr.h"
#include "MsgStorage.pb.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_CARD , CCmdCard);

int CCmdCard::Do(void* pData)
{
    CT_ASSERT(pData);
    int iRet = 0;

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_CARD ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Type=%d",
            ID_MAIN_CARD,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    uiGID = (unsigned int)stReq.gid();

    //检查登录
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return iRet;
}

int CCmdCard::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_EX1_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_EX1_INFO(uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, uiGID);

    int iIndex;
    iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", uiGID));
        pstMainCtrl->SetOffline(stPlayerBaseInfo._uiGID, stEnpHead);
        return AnsClients(RET_SYSTEM_FAIL);

    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //检查系统是否开启
    if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_19, stPlayerBaseInfo, stPlayerOnlineData))
    {
        return AnsClients(ERROR_SYS_NOT_OPEN);
    }
    
    unsigned char ucOptType = stReq.opt();
    bool bNeedSaveData = false;
    switch(ucOptType)
    {
    case 1: //查询占卜信息
        pstMainCtrl->m_stCardMgr.SendDivineInfoToFront(stPlayerOnlineData._stUserCard, stPlayerBaseInfo, stPlayerDetailInfo._stUserDivine,
                        stMsgHead, stEnpHead);
        break;
    case 2: //翻牌
        {
            iRet = pstMainCtrl->m_stCardMgr.TurnOverCard(stPlayerBaseInfo, stPlayerDetailInfo, stTurnOverAns);
            if (iRet != 0)
            {
                return AnsClients(iRet);
            }

            MsgUserGold* pstMsgUserGold = stTurnOverAns.mutable_gold();
            pstMsgUserGold->set_vip_level(stPlayerBaseInfo._chVipLevel);
            pstMsgUserGold->set_gold(stPlayerBaseInfo._iGold);
            CTSizeString<50> szSilver;
            szSilver.Set("%lld", stPlayerBaseInfo._i64Silver);
            pstMsgUserGold->set_silver(szSilver());
            pstMsgUserGold->set_romany(stPlayerBaseInfo._iRomany);

            bNeedSaveData = true;

            //触发任务
            pstMainCtrl->m_stTaskMgr.TriggerDoSomeOpt(stPlayerOnlineData._stUserTask, TASK_OPT_ID_111, 1);
            CMainCtrl::m_pstMain->m_stDailyTaskMgr.TriggerTaskFinish(stPlayerOnlineData._stUserDailyTask, DAILY_TASK_ID_12);
        }
        break;
    case 3: //全部收取
    case 4: //带合成功能的全部收取
        {
            CT_TRACE(("CCardMgr: ============== before drop =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

            pstMainCtrl->m_stOssMgr.ClearKeyValueList();//oss

            CT_TRACE(("drop before: face force = %d", stPlayerBaseInfo._iFateForce));

            iRet = pstMainCtrl->m_stCardMgr.DropCard(stPlayerOnlineData._stUserCard, stPlayerBaseInfo,
                                stPlayerDetailInfo, ucOptType == 4);

            pstMainCtrl->m_stCardMgr.SendDivineInfoToFront(stPlayerOnlineData._stUserCard, stPlayerBaseInfo, stPlayerDetailInfo._stUserDivine,
                                    stMsgHead, stEnpHead);

            pstMainCtrl->m_stCardMgr.SendCardBagInfoToFront(stPlayerOnlineData._stUserCard, stMsgHead, stEnpHead);

            bNeedSaveData = true;

            CT_TRACE(("drop after: face force = %d", stPlayerBaseInfo._iFateForce));
            CT_TRACE(("CCardMgr: ============== after drop =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

            pstMainCtrl->m_stOssMgr.TriggerItem(uiGID, OSS_ITEM_COLLECT_CARD);//oss
        }
        break;
    case 5: // 一键合成背包卡片
        {
            CT_TRACE(("CCardMgr: ============== before merge =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

            pstMainCtrl->m_stOssMgr.ClearKeyValueList();//oss

            iRet = pstMainCtrl->m_stCardMgr.MergeCardBag(stPlayerOnlineData._stUserCard, stPlayerDetailInfo);
            bNeedSaveData = true;

            pstMainCtrl->m_stOssMgr.TriggerItem(uiGID, OSS_ITEM_MERGE_CARD);//oss

            pstMainCtrl->m_stCardMgr.SendCardBagInfoToFront(stPlayerOnlineData._stUserCard, stMsgHead, stEnpHead);

            CT_TRACE(("CCardMgr: ============== after merge =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);
        }
        break;
    case 6: //兑换卡片
        {
            pstMainCtrl->m_stOssMgr.ClearKeyValueList();//oss

            iRet = pstMainCtrl->m_stCardMgr.ExchangeCard(stPlayerOnlineData._stUserCard, stReq.card_cfg_id(),
                                stPlayerBaseInfo._shLevel, stPlayerBaseInfo._iRomany, stPlayerDetailInfo);

            if (RET_OK == iRet)
            {
                bNeedSaveData = true;
                pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_USER_MONEY);

                pstMainCtrl->m_stCardMgr.SendCardBagInfoToFront(stPlayerOnlineData._stUserCard, stMsgHead, stEnpHead);
            }

            pstMainCtrl->m_stOssMgr.TriggerItem(uiGID, OSS_ITEM_EXCHANGE_CARD);//oss
        }
        break;
    case 7: //金币占卜
        {
            int iMaxDivineCount = 0;
            iRet = pstMainCtrl->m_stVipMgr.GetVipDestNum(stPlayerBaseInfo._chVipLevel, VIP_MODULE_ID_25, iMaxDivineCount);
            if (RET_OK != iRet)
            {
                return AnsClients(iRet);
            }

            iRet = pstMainCtrl->m_stCardMgr.GoldTurnOverCard(stPlayerBaseInfo, stPlayerDetailInfo, iMaxDivineCount, stTurnOverAns);

            if (RET_OK == iRet)
            {
                bNeedSaveData = true;

                stTurnOverAns.set_can_gold_divine_count(pstMainCtrl->m_stCardMgr.GetGoldTurnOverCount(stPlayerBaseInfo._chVipLevel, 
                    stPlayerDetailInfo._stUserDivine._stHasGoldDivineCount.Get(pstMainCtrl->m_iNow)));

                //触发任务
                CMainCtrl::m_pstMain->m_stDailyTaskMgr.TriggerTaskFinish(stPlayerOnlineData._stUserDailyTask, DAILY_TASK_ID_12);
            }
        }
        break;
    case 8: // 查询金币占卜信息
        {
            int iMaxDivineCount = 0;
            iRet = pstMainCtrl->m_stVipMgr.GetVipDestNum(stPlayerBaseInfo._chVipLevel, VIP_MODULE_ID_25, iMaxDivineCount);
            if (RET_OK != iRet)
            {
                return AnsClients(iRet);
            }

            stTurnOverAns.set_can_gold_divine_count(pstMainCtrl->m_stCardMgr.GetGoldTurnOverCount(stPlayerBaseInfo._chVipLevel, 
                                                                                    stPlayerDetailInfo._stUserDivine._stHasGoldDivineCount.Get(pstMainCtrl->m_iNow)));
            
            for (int i = 0; i < stPlayerDetailInfo._stUserDivine._ausGoldDivineCards.Size(); ++i)
            {
                stTurnOverAns.add_gold_divine_bag(stPlayerDetailInfo._stUserDivine._ausGoldDivineCards[i]);
            }
        }
        break;
    case 9: //全部收取金币占卜结果
        {
            pstMainCtrl->m_stOssMgr.ClearKeyValueList();//oss

            iRet = pstMainCtrl->m_stCardMgr.GoldDropCard(stPlayerOnlineData._stUserCard, stPlayerBaseInfo, stPlayerDetailInfo, stTurnOverAns);
        
            if (RET_OK == iRet)
            {
                bNeedSaveData = true;

                stTurnOverAns.set_can_gold_divine_count(pstMainCtrl->m_stCardMgr.GetGoldTurnOverCount(stPlayerBaseInfo._chVipLevel, 
                    stPlayerDetailInfo._stUserDivine._stHasGoldDivineCount.Get(pstMainCtrl->m_iNow)));

                pstMainCtrl->m_stCardMgr.SendCardBagInfoToFront(stPlayerOnlineData._stUserCard, stMsgHead, stEnpHead);
            }

            pstMainCtrl->m_stOssMgr.TriggerItem(uiGID, OSS_ITEM_COLLECT_CARD);//oss

        }
        break;
    default:
        return AnsClients(RET_SYS_ERROR);
    }

    if (bNeedSaveData)
    {
        //保存数据
        pstMainCtrl->m_stCardMgr.GetData(stPlayerOnlineData._stUserCard, stPlayerDetailInfo._stUserCardData);

        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        stKey.m_u64ID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    return AnsClients(iRet);
}

int CCmdCard::AnsClients(int iRet)
{
    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != 0)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();

    switch(stReq.opt())
    {
    case 1:
        pstMainCtrl->FlushSendCache();
        break;
    case 2:
    case 7:
    case 8:
    case 9:
        {
            stMsgHead.set_msgid(ID_MAIN_CARD_TURN_OVER_CARD);
            CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
            CMainCtrl::m_pstMain->EncodePBMsg(stTurnOverAns, CMainCtrl::m_pstMain->m_stEncodeBuf);
            pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true);
        }
        break;
    default:
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        break;
    }

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////

CT_REGISTER_ASYNCCMD(ID_MAIN_CARD_ROLE , CCmdCardRole);

int CCmdCardRole::Do(void* pData)
{
    CT_ASSERT(pData);
    int iRet = 0;

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_CARD_ROLE ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Type=%d",
            ID_MAIN_CARD_ROLE,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    uiGID = (unsigned int)stReq.gid();

    //检查登录
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return iRet;
}

int CCmdCardRole::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, uiGID);

    int iIndex;
    iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", uiGID));
        pstMainCtrl->SetOffline(stPlayerBaseInfo._uiGID, stEnpHead);
        return AnsClients(RET_SYSTEM_FAIL);

    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    int iRoleID = stReq.partner_id();
    stAns.set_partner_id(iRoleID);

    //用于存放结果

    switch(stReq.oper_type())
    {
    case 1: //穿
        {
            CT_TRACE(("CCardMgr: ============== before ware =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

            MsgAnsItemBaseInfos stFromCardAns;
            MsgAnsItemBaseInfos stToCardAns;
            MsgGridItemInfo* pstFromCardInfo = stFromCardAns.add_infos();
            MsgGridItemInfo* pstToCardInfo = stToCardAns.add_infos();

            stFromCardAns.set_storage_type(STORAGE_TYPE_CARD);
            stToCardAns.set_storage_type(STORAGE_TYPE_ROLE_CARD);

            if (iRoleID == 0)
            {
                iRet = pstMainCtrl->m_stCardMgr.WareCard(stPlayerOnlineData._stUserCard, stPlayerDetailInfo._stPlayerWareCard, iRoleID,
                    stPlayerBaseInfo._shLevel, (unsigned short)stReq.card_from_pos(), (unsigned char)stReq.card_to_pos(), stPlayerDetailInfo);

                if (RET_OK == iRet)
                {
                    unsigned int uiNowCardIdOnRole = 0;
                    stPlayerDetailInfo._stPlayerWareCard.GetCardByPos(stReq.card_to_pos(), uiNowCardIdOnRole);
                    pstMainCtrl->m_stCardMgr.GetCardInfo(stPlayerOnlineData._stUserCard, stPlayerDetailInfo, uiNowCardIdOnRole, *pstToCardInfo);

                    //更新属性
                    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, NOTIFY_ROLE_ATTR);
                }
            }
            else
            {
                int iIndex = stPlayerDetailInfo._stUserPartner.FindActData(iRoleID);
                if (iIndex < 0)
                {
                    return AnsClients(ERROR_CARD_NO_PARTNER);
                }

                CPartnerActData& stPartner = stPlayerDetailInfo._stUserPartner.GetPartnerActData(iIndex);

                iRet = pstMainCtrl->m_stCardMgr.WareCard(stPlayerOnlineData._stUserCard, stPartner._stPlayerWareCard, iRoleID,
                    stPartner._shLevel, (unsigned short)stReq.card_from_pos(), (unsigned char)stReq.card_to_pos(), stPlayerDetailInfo);

                if (RET_OK == iRet)
                {
                    unsigned int uiNowCardIdOnRole = 0;
                    stPartner._stPlayerWareCard.GetCardByPos(stReq.card_to_pos(), uiNowCardIdOnRole);
                    pstMainCtrl->m_stCardMgr.GetCardInfo(stPlayerOnlineData._stUserCard, stPlayerDetailInfo, uiNowCardIdOnRole, *pstToCardInfo);

                    //更新属性
                    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, NOTIFY_PARTNER_ATTR, iRoleID);
                }
            }

            pstFromCardInfo->set_item_store_pos(stReq.card_from_pos());
            pstFromCardInfo->set_item_type(0);

            //获取当前状态信息
            if (iRet == RET_OK)
            {
                //发送消息
                PBMsgHead stTempMsgHead = stMsgHead;
                stTempMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
                stTempMsgHead.set_msgid(ID_MAIN_GRID_BASE_INFO);
                stTempMsgHead.set_msgret(RET_OK);

                pstMainCtrl->m_stEncodeBuf.Clear();
                stFromCardAns.set_partner_id(iRoleID);
                pstMainCtrl->EncodePBMsg(stTempMsgHead, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->EncodePBMsg(stFromCardAns, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf);

                pstMainCtrl->m_stEncodeBuf.Clear();
                stToCardAns.set_partner_id(iRoleID);
                pstMainCtrl->EncodePBMsg(stTempMsgHead, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->EncodePBMsg(stToCardAns, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf);

                pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_CARD_POINT, iRoleID);
            }

            CT_TRACE(("CCardMgr: ============== after ware =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);
        }
        break;
    case 2: //脱
        {
            CT_TRACE(("CCardMgr: ============== before takeoff =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

            MsgAnsItemBaseInfos stFromCardAns;
            MsgAnsItemBaseInfos stToCardAns;
            MsgGridItemInfo* pstFromCardInfo = stFromCardAns.add_infos();
            MsgGridItemInfo* pstToCardInfo = stToCardAns.add_infos();

            stFromCardAns.set_storage_type(STORAGE_TYPE_ROLE_CARD);
            stToCardAns.set_storage_type(STORAGE_TYPE_CARD);
            pstFromCardInfo->set_item_store_pos(stReq.card_take_off_pos());
            pstFromCardInfo->set_item_config_id(0);

            unsigned short usBagPos = 0;
            if (stReq.dest_to_pos() < 0)
            {
                usBagPos = STORAGE_POS_NOT_OCCUPIED;
            }
            else
            {
                usBagPos = stReq.dest_to_pos();
            }

            if (iRoleID == 0)
            {
                iRet = pstMainCtrl->m_stCardMgr.TakeOffCard(stPlayerOnlineData._stUserCard, stPlayerDetailInfo._stPlayerWareCard,
                    (unsigned char)stReq.card_take_off_pos(), usBagPos);

                if (RET_OK == iRet)
                {
                    //更新属性
                    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, NOTIFY_ROLE_ATTR);
                }
            }
            else
            {
                int iIndex = stPlayerDetailInfo._stUserPartner.FindActData(iRoleID);
                if (iIndex < 0)
                {
                    return AnsClients(ERROR_CARD_NO_PARTNER);
                }

                CPartnerActData& stPartner = stPlayerDetailInfo._stUserPartner.GetPartnerActData(iIndex);

                iRet = pstMainCtrl->m_stCardMgr.TakeOffCard(stPlayerOnlineData._stUserCard, stPartner._stPlayerWareCard,
                                        (unsigned char)stReq.card_take_off_pos(), usBagPos);

                if (RET_OK == iRet)
                {
                    //更新属性
                    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, NOTIFY_PARTNER_ATTR, iRoleID);
                }
            }

            if (RET_OK == iRet)
            {
                pstMainCtrl->m_stCardMgr.GetCardInfoByPos(stPlayerOnlineData._stUserCard, stPlayerDetailInfo, usBagPos, *pstToCardInfo);

                //发送消息
                PBMsgHead stTempMsgHead = stMsgHead;
                stTempMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
                stTempMsgHead.set_msgid(ID_MAIN_GRID_BASE_INFO);
                stTempMsgHead.set_msgret(RET_OK);

                pstMainCtrl->m_stEncodeBuf.Clear();
                stFromCardAns.set_partner_id(iRoleID);
                pstMainCtrl->EncodePBMsg(stTempMsgHead, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->EncodePBMsg(stFromCardAns, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf);

                pstMainCtrl->m_stEncodeBuf.Clear();
                stToCardAns.set_partner_id(iRoleID);
                pstMainCtrl->EncodePBMsg(stTempMsgHead, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->EncodePBMsg(stToCardAns, pstMainCtrl->m_stEncodeBuf);
                pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf);
            }

            CT_TRACE(("CCardMgr: ============== after takeoff =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

            pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_CARD_POINT, iRoleID);
        }
        break;
    case 3: //移动卡片
        {
            CT_TRACE(("CCardMgr: ============== before move =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

            unsigned char ucFromPos = stReq.card_from_pos();
            unsigned char ucToPos = stReq.card_to_pos();

            CStorageGrid stGrid1;
            CStorageGrid stGrid2;
            iRet = pstMainCtrl->m_stCardMgr.SwapStorageItemPos(stPlayerOnlineData._stUserCard, ucFromPos, stGrid1, ucToPos, stGrid2);

            CT_TRACE(("CCardMgr: ============== after move =============="));
            pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);
        }
        break;
    case 4: //身上的卡片位置移动
        {
            if (iRoleID == 0)
            {
                iRet = pstMainCtrl->m_stCardMgr.MoveWareCard(stPlayerOnlineData._stUserCard, stPlayerDetailInfo._stPlayerWareCard, iRoleID,
                    stPlayerBaseInfo._shLevel, (unsigned short)stReq.card_from_pos(), (unsigned char)stReq.card_to_pos());
            }
            else
            {
                int iIndex = stPlayerDetailInfo._stUserPartner.FindActData(iRoleID);
                if (iIndex < 0)
                {
                    return AnsClients(ERROR_CARD_NO_PARTNER);
                }

                CPartnerActData& stPartner = stPlayerDetailInfo._stUserPartner.GetPartnerActData(iIndex);

                iRet = pstMainCtrl->m_stCardMgr.MoveWareCard(stPlayerOnlineData._stUserCard, stPartner._stPlayerWareCard, iRoleID,
                            stPartner._shLevel, (unsigned short)stReq.card_from_pos(), (unsigned char)stReq.card_to_pos());
            }
        }
        break;
    default:
        return AnsClients(RET_SYS_ERROR);
    }

    //保存数据
    pstMainCtrl->m_stCardMgr.GetData(stPlayerOnlineData._stUserCard, stPlayerDetailInfo._stUserCardData);

    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_BASE_INFO;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

    stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    stKey.m_u64ID = stPlayerDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);

    return AnsClients(iRet);
}

int CCmdCardRole::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////
CT_REGISTER_ASYNCCMD(ID_MAIN_CARD_VORTEX , CCmdCardVortex);

int CCmdCardVortex::Do(void* pData)
{
    CT_ASSERT(pData);
    int iRet = 0;

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_CARD_VORTEX ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Type=%d",
            ID_MAIN_CARD_VORTEX,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    uiGID = (unsigned int)stReq.gid();

    //检查登录
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return iRet;
}

int CCmdCardVortex::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, uiGID);

    int iIndex;
    iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("%u", uiGID));
        return AnsClients(RET_SYS_ERROR);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("%u", uiGID));
        return AnsClients(RET_SYS_ERROR);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("%u", uiGID));
        return AnsClients(RET_SYS_ERROR);
    }

    int iRoleID = stReq.role_id();
    unsigned char ucOptType = (unsigned char)stReq.opt();

    stAns.set_opt(ucOptType);
    stAns.set_role_id(iRoleID);

    bool bNeedSaveData = false;
    switch(ucOptType)
    {
    case 1: //查询
        {
            iRet = GetNowStat(iRoleID, stPlayerBaseInfo, stPlayerDetailInfo);
        }
        break;
    case 2: //升级
        {
            CT_TRACE(("before level up: face force = %d", stPlayerBaseInfo._iFateForce));

            if (iRoleID == 0) //主角
            {
                CCardVortex& stCardVortex = stPlayerDetailInfo._stCardVortex;
                iRet = pstMainCtrl->m_stCardMgr.VortexLevelUp(stPlayerBaseInfo._iFateForce, stCardVortex);

                //重新计算属性
                pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_ROLE_ATTR | NOTIFY_ROLE_INFO);
            }
            else
            {
                int iIndex = stPlayerDetailInfo._stUserPartner.FindActData(iRoleID);
                if (iIndex < 0)
                {
                    return AnsClients(ERROR_CARD_NO_PARTNER);
                }

                CPartnerActData& stPartner = stPlayerDetailInfo._stUserPartner.GetPartnerActData(iIndex);

                CCardVortex& stCardVortex = stPartner._stCardVortex;
                iRet = pstMainCtrl->m_stCardMgr.VortexLevelUp(stPlayerBaseInfo._iFateForce, stCardVortex);

                //重新计算属性
                pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_PARTNER_ATTR | NOTIFY_PARTNER_INFO, iRoleID);
            }

            if (iRet != RET_OK)
            {
                return AnsClients(iRet);
            }

            GetNowStat(iRoleID, stPlayerBaseInfo, stPlayerDetailInfo);
            bNeedSaveData = true;

            CT_TRACE(("after level up: face force = %d", stPlayerBaseInfo._iFateForce));
        }
        break;
    case 3: //抽取1级
    case 4: //抽取所有
        {
            CT_TRACE(("before level down: face force = %d", stPlayerBaseInfo._iFateForce));

            if (iRoleID == 0) //主角
            {
                CCardVortex& stCardVortex = stPlayerDetailInfo._stCardVortex;
                iRet = pstMainCtrl->m_stCardMgr.VortexLevelDown(stPlayerBaseInfo._iFateForce, stPlayerBaseInfo, stCardVortex, ucOptType == 4);
            
                //重新计算属性
                pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_ROLE_ATTR | NOTIFY_ROLE_INFO);
            }
            else
            {
                int iIndex = stPlayerDetailInfo._stUserPartner.FindActData(iRoleID);
                if (iIndex < 0)
                {
                    return AnsClients(ERROR_CARD_NO_PARTNER);
                }

                CPartnerActData& stPartner = stPlayerDetailInfo._stUserPartner.GetPartnerActData(iIndex);

                CCardVortex& stCardVortex = stPartner._stCardVortex;
                iRet = pstMainCtrl->m_stCardMgr.VortexLevelDown(stPlayerBaseInfo._iFateForce, stPlayerBaseInfo, stCardVortex, ucOptType == 4);
            
                //重新计算属性
                pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_PARTNER_ATTR | NOTIFY_PARTNER_INFO, iRoleID);
            }

            if (iRet != RET_OK)
            {
                return AnsClients(iRet);
            }

            GetNowStat(iRoleID, stPlayerBaseInfo, stPlayerDetailInfo);
            bNeedSaveData = true;
            pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_USER_MONEY);

            CT_TRACE(("after level down: face force = %d", stPlayerBaseInfo._iFateForce));
        }
        break;
    default:
        iRet = RET_SYS_ERROR;
    }

    //保存数据
    if (bNeedSaveData)
    {
        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        stKey.m_u64ID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    return AnsClients(iRet);
}

int CCmdCardVortex::GetNowStat(int iRoleID, CPlayerBaseInfo stPlayerBaseInfo, CPlayerDetailInfo& stPlayerDetailInfo)
{
    int iRet = 0;
    stAns.set_gid(stPlayerBaseInfo._uiGID);
    stAns.set_total(stPlayerBaseInfo._iFateForce);

    CCardVortex stCardVortex;
    if (iRoleID == 0) //主角
    {
        stCardVortex = stPlayerDetailInfo._stCardVortex;
    }
    else
    {
        int iIndex = stPlayerDetailInfo._stUserPartner.FindActData(iRoleID);
        if (iIndex < 0)
        {
            return ERROR_CARD_NO_PARTNER;
        }

        CPartnerActData& stPartner = stPlayerDetailInfo._stUserPartner.GetPartnerActData(iIndex);

        stCardVortex = stPartner._stCardVortex;
    }

    stAns.set_now_count(stCardVortex._iTotalFateForce);
    stAns.set_now_level(stCardVortex._usLevel);

    CVortexConfigData stNowLevelConfigData;
    iRet = pstMainCtrl->m_stCardMgr.GetVortexConfig(stCardVortex._usLevel, stNowLevelConfigData);
    CHECK_RETURN(iRet);

    CVortexConfigData stNextLevelConfigData;
    iRet = pstMainCtrl->m_stCardMgr.GetVortexConfig(stCardVortex._usLevel + 1, stNextLevelConfigData);
    CHECK_RETURN(iRet);

    stAns.set_next_level_count(stNextLevelConfigData._uiNeedFateForceCount);
    stAns.set_now_effect_count(stNowLevelConfigData._usAddProp);
    stAns.set_next_effect_count(stNextLevelConfigData._usAddProp);

    return 0;
}

int CCmdCardVortex::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

//////////////////////////////////////////////////////////////////////////
CT_REGISTER_ASYNCCMD(ID_MAIN_CARD_COMB , CCmdCardComb);

int CCmdCardComb::Do(void* pData)
{
    CT_ASSERT(pData);
    int iRet = 0;

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_CARD_COMB ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Type=%d",
            ID_MAIN_CARD_COMB,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    uiGID = (unsigned int)stReq.gid();

    //检查登录
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return iRet;
}

int CCmdCardComb::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_EX1_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_EX1_INFO(uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, uiGID);

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //逻辑处理开始
    unsigned int uiFromCardID = stReq.drag_card_id();
    unsigned int uiToCardID = stReq.to_card_id();
    unsigned int uiDestCardID = 0;

    CSingleCardData stFromCardInfo;
    CSingleCardData stToCardInfo;
    iRet = pstMainCtrl->m_stCardMgr.GetCardInfo(stPlayerOnlineData._stUserCard, uiFromCardID, stFromCardInfo);
    if (RET_OK != iRet)
    {
        return AnsClients(iRet);
    }

    iRet = pstMainCtrl->m_stCardMgr.GetCardInfo(stPlayerOnlineData._stUserCard, uiToCardID, stToCardInfo);
    if (RET_OK != iRet)
    {
        return AnsClients(iRet);
    }

    CT_TRACE(("CCardMgr: ============== before combine =============="));
    pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

    MsgAnsItemBaseInfos stFromCardAns;
    MsgAnsItemBaseInfos stToCardAns;
    stFromCardAns.set_partner_id(stFromCardInfo._iWareRoleID);
    stFromCardAns.set_storage_type(stFromCardInfo._ucIsWare ? STORAGE_TYPE_ROLE_CARD : STORAGE_TYPE_CARD);
    stToCardAns.set_partner_id(stToCardInfo._iWareRoleID);
    stToCardAns.set_storage_type(stToCardInfo._ucIsWare ? STORAGE_TYPE_ROLE_CARD : STORAGE_TYPE_CARD);

    MsgGridItemInfo* pstFromCardInfo = stFromCardAns.add_infos();
    MsgGridItemInfo* pstToCardInfo = stToCardAns.add_infos();

    pstMainCtrl->m_stCardMgr.GetCardInfo(stPlayerOnlineData._stUserCard, stPlayerDetailInfo, uiFromCardID, *pstFromCardInfo);
    pstMainCtrl->m_stCardMgr.GetCardInfo(stPlayerOnlineData._stUserCard, stPlayerDetailInfo, uiToCardID, *pstToCardInfo);

    pstMainCtrl->m_stOssMgr.ClearKeyValueList();//oss
    iRet = pstMainCtrl->m_stCardMgr.CardCombine(stPlayerOnlineData._stUserCard, stPlayerDetailInfo, uiFromCardID, uiToCardID, true, uiDestCardID);
    pstMainCtrl->m_stOssMgr.TriggerItem(uiGID, OSS_ITEM_COMBINE_CARD);//oss
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    //返回信息
    if (iRet == RET_OK)
    {
        pstFromCardInfo->set_item_type(0);
        pstFromCardInfo->set_item_config_id(0);
        pstFromCardInfo->set_item_count(0);        
        pstMainCtrl->m_stCardMgr.GetCardInfo(stPlayerOnlineData._stUserCard, stPlayerDetailInfo, uiDestCardID, *pstToCardInfo);

        //发送
        PBMsgHead stTempMsgHead = stMsgHead;
        stTempMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);
        stTempMsgHead.set_msgid(ID_MAIN_GRID_BASE_INFO);
        stTempMsgHead.set_msgret(RET_OK);

        pstMainCtrl->m_stEncodeBuf.Clear();
        pstMainCtrl->EncodePBMsg(stTempMsgHead, pstMainCtrl->m_stEncodeBuf);
        pstMainCtrl->EncodePBMsg(stFromCardAns, pstMainCtrl->m_stEncodeBuf);
        pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf);

        pstMainCtrl->m_stEncodeBuf.Clear();
        pstMainCtrl->EncodePBMsg(stTempMsgHead, pstMainCtrl->m_stEncodeBuf);
        pstMainCtrl->EncodePBMsg(stToCardAns, pstMainCtrl->m_stEncodeBuf);
        pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf);

        if (stFromCardInfo._ucIsWare)
        {
            pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_CARD_POINT, stFromCardInfo._iWareRoleID);
        }
        else if (stToCardInfo._ucIsWare)
        {
            pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_CARD_POINT, stToCardInfo._iWareRoleID);
        }
    }

    CT_TRACE(("CCardMgr: ============== after combine =============="));
    pstMainCtrl->m_stCardMgr.DumpCardInfo(stPlayerOnlineData._stUserCard);

    //保存数据
    pstMainCtrl->m_stCardMgr.GetData(stPlayerOnlineData._stUserCard, stPlayerDetailInfo._stUserCardData);

    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
    stKey.m_u64ID = stPlayerDetailInfo._uiGID;
    pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);

    return AnsClients(iRet);
}

int CCmdCardComb::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);

    return Done(iRet);
}



